package dtrs.corba.serverSide;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Hashtable;

import org.omg.CORBA.ORB;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.PortableServer.POA;

import MyBoxOfficeServer.MyService;
import MyBoxOfficeServer.MyServicePOA;
import MyBoxOfficeServer.MyServiceHelper;
import dtrs.corba.utilities.DtrsConstants;
import dtrs.corba.utilities.DtrsGeneralUtilities;

public class ServerSideMain {

	public static void main(String[] args) {


		try {

			initProcessLoadServer();

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		


	}


	/*
	 * check if box Office is valid to start up the server in the nameService
	 */
	private static boolean initProcessLoadServer(){

		boolean displayMsgServerName = true;
		

		InputStreamReader inputReader = new InputStreamReader(System.in);
		BufferedReader bufferedReader = new BufferedReader(inputReader);

		try{

			System.out.println("--**************************--");
			System.out.println("SERVER TO DTRS (Distributed Ticket Reservation System)");

			while(displayMsgServerName){

				int i=0;
				for(DtrsConstants.BOX_OFFICE boxOffice:  DtrsConstants.BOX_OFFICE.values()){
					System.out.println(i+1+"." + boxOffice);
					i++;			
				}
				System.out.println(i+1+"." + "Exit");

				System.out.print("Select one box office server:");	

				String serverBoxOfficeIden = (bufferedReader.readLine()).trim();	

				if(!DtrsGeneralUtilities.validStringOnlyNumber(serverBoxOfficeIden) ||
						serverBoxOfficeIden.length()> 1 || 
						Integer.valueOf(serverBoxOfficeIden) > DtrsConstants.NUMBER_OF_SERVERS+1  ){

					System.out.println("Not a valid selection.");

				}else if(Integer.valueOf(serverBoxOfficeIden) <= DtrsConstants.NUMBER_OF_SERVERS ){

					startServerInNamingService(Integer.valueOf(serverBoxOfficeIden));
					displayMsgServerName = false;


				} else if (Integer.valueOf(serverBoxOfficeIden) == DtrsConstants.NUMBER_OF_SERVERS + 1){
					System.out.println("Thanks ans bye!!");
					return false;
				}	
			}


		}catch(Exception ie){
			ie.printStackTrace();
		}


		return true;

	}



	private static void startServerInNamingService(int serverSelected){


		switch(serverSelected){

		case 1:
			addBoxOfficeServerInNamingContext(DtrsConstants.PORT_SERVER_MONTREAL,
					DtrsConstants.URL_GENERAL_LOCALHOST,
					DtrsConstants.BOX_MONTREAL);
			break;
		case 2:
			addBoxOfficeServerInNamingContext(DtrsConstants.PORT_SERVER_TORONTO,
					DtrsConstants.URL_GENERAL_LOCALHOST,
					DtrsConstants.BOX_TORONTO);
			break;
		case 3:
			addBoxOfficeServerInNamingContext(DtrsConstants.PORT_SERVER_EDMONTON,
					DtrsConstants.URL_GENERAL_LOCALHOST,
					DtrsConstants.BOX_EDMONTON);
			break;
		case 4:
			addBoxOfficeServerInNamingContext(DtrsConstants.PORT_SERVER_REGINA,
					DtrsConstants.URL_GENERAL_LOCALHOST,
					DtrsConstants.BOX_REGINA);
			break;
		case 5:
			addBoxOfficeServerInNamingContext(DtrsConstants.PORT_SERVER_WINNIPEG,
					DtrsConstants.URL_GENERAL_LOCALHOST,
					DtrsConstants.BOX_WINNIPEG);
			break;	
		case 6:
			break;
		}

	}




	/**
	 * 
	 * @param hostServerNameP
	 * @param portServerP	port on which you want the name server to run
	 * @param serverName
	 */
	private static void addBoxOfficeServerInNamingContext(String portServerP,
			String hostServerNameP,
			String serverName){
		
		Hashtable<String,ServerLocation> serverPorts = new Hashtable<String,ServerLocation>();

		// loads the address and port of each Server for UDP/IPC server to server communication.
		serverPorts = ServerLocations(); 
		
		try{

			//-ORBInitialPort 1050 -ORBInitialHost localhost
			String[] argInitOrb = new String[4];
			argInitOrb[0] = DtrsConstants.ORB_PORT_KEY_WORD;
			argInitOrb[1] = portServerP;
			argInitOrb[2] = DtrsConstants.ORB_HOST_KEY_WORD;
			argInitOrb[3] = hostServerNameP;


			// create and initialize the ORB
			ORB orb = ORB.init(argInitOrb, null);

			// get reference to rootpoa & activate the POAManager
			POA rootpoa =  (POA)orb.resolve_initial_references("RootPOA");
			rootpoa.the_POAManager().activate();

			// create servant and register it with the ORB
			DTRSServerServant serverImpl = new DTRSServerServant(serverName, serverPorts);
			(new Thread(serverImpl)).start();
			
			serverImpl.setORB(orb);

			// get object reference from the servant
			org.omg.CORBA.Object ref =
				rootpoa.servant_to_reference(serverImpl);

			// and cast the reference to a CORBA reference
			MyService href = MyServiceHelper.narrow(ref);

			// get the root naming context
			// NameService invokes the transient name service
			org.omg.CORBA.Object objRef =
				orb.resolve_initial_references("NameService");

			// Use NamingContextExt, which is part of the
			// Interoperable Naming Service (INS) specification.
			NamingContextExt ncRef =
				NamingContextExtHelper.narrow(objRef);


			// bind the Object Reference in Naming
			NameComponent path[] = ncRef.to_name( serverName );
			ncRef.rebind(path, href);
			System.out.println("Server "+ serverName + " ready and waiting ...");

			// wait for invocations from clients
			orb.run();
			

		}catch(Exception ie){
			ie.printStackTrace();
		}

	}


	// Method that returns a hash table containing the location of all servers of the distributed system, as loaded from a file
	public static Hashtable<String,ServerLocation> ServerLocations(){
		

		ServerLocation aLocation;
		Hashtable<String,ServerLocation> locations = new Hashtable<String,ServerLocation>();

		try { 


			aLocation = new ServerLocation(DtrsConstants.BOX_MONTREAL,
										   DtrsConstants.URL_GENERAL_LOCALHOST,
										   DtrsConstants.PORT_UDP_SERVER_MONTREAL);
			locations.put(aLocation.getOffice(), aLocation);

			aLocation = new ServerLocation(DtrsConstants.BOX_TORONTO,
										   DtrsConstants.URL_GENERAL_LOCALHOST,
										   DtrsConstants.PORT_UDP_SERVER_TORONTO);
			
			locations.put(aLocation.getOffice(), aLocation);
			
			
			aLocation = new ServerLocation(DtrsConstants.BOX_EDMONTON,
										   DtrsConstants.URL_GENERAL_LOCALHOST,
										   DtrsConstants.PORT_UDP_SERVER_EDMONTON);

			locations.put(aLocation.getOffice(), aLocation);
	
			aLocation = new ServerLocation(DtrsConstants.BOX_REGINA,
										   DtrsConstants.URL_GENERAL_LOCALHOST,
										   DtrsConstants.PORT_UDP_SERVER_REGINA);

			locations.put(aLocation.getOffice(), aLocation);
			
			
			aLocation = new ServerLocation(DtrsConstants.BOX_WINNIPEG,
										   DtrsConstants.URL_GENERAL_LOCALHOST,
										   DtrsConstants.PORT_UDP_SERVER_WINNIPEG);

			locations.put(aLocation.getOffice(), aLocation);



		} catch (Exception e) { 
			System.out.println("Error loading server locations for IPC communication on UDP.");
			e.printStackTrace();
		}
		return locations;
	}


}


